package com.millstein.tsinglog.service.impl;

import com.millstein.tsinglog.commons.constant.SystemConstant;
import com.millstein.tsinglog.commons.enums.ResultCode;
import com.millstein.tsinglog.exception.TsinglogException;
import com.millstein.tsinglog.commons.service.BaseService;
import com.millstein.tsinglog.mapper.biz.PermissionMapper;
import com.millstein.tsinglog.mapper.biz.RoleMapper;
import com.millstein.tsinglog.mapper.biz.UserMapper;
import com.millstein.tsinglog.model.pojo.Permission;
import com.millstein.tsinglog.model.pojo.User;
import com.millstein.tsinglog.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl extends BaseService implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<Permission> getAllPermissions() {
        Example example = new Example(Permission.class);
        Example.Criteria criteria = example.createCriteria();

        criteria.andEqualTo("status", SystemConstant.STATUS_ENTITY_NORMAL);
        example.setOrderByClause("parent_id asc, sort asc");

        List<Permission> permissions = permissionMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(permissions)) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }

        return permissions;
    }

    @Override
    public List<Permission> getPermissionByRole(Long roleId, Boolean forProfile) {
        if (roleId == null) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }
        // 1.根据roleId查中间表，得到该roleId对应的所有的permissionId
        List<Map<String, Object>> list = roleMapper.getMultipleRelations(roleId);

        if (CollectionUtils.isEmpty(list)) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        List<Long> permissionIds =
                list.stream().map(item -> ((Integer) item.get("permission_id")).longValue()).collect(Collectors.toList());

        List<Permission> permissions = permissionMapper.selectByIdList(permissionIds);

        // forProfile为true时需要额外添加可见菜单对应的权限，为false时不需要
        if (forProfile) {
            /*
            情况一：如果给某个角色分配的二级菜单权限不完整，会造成有权限而看不到菜单的情况
            在这里我们约定如果某个角色拥有权限代码以query结尾的权限，那么这个角色就能看到这个模块；如果没有query结尾的权限，那么就不给看

            情况二：如果给某个角色分配的一级菜单权限不完整，会造成有权限看不到父菜单的情况
            在这里我们约定如果某个角色拥有权限代码以view结尾的权限，那么这个角色就能看到这个菜单的父菜单

            所以在这里我们需要手动填补以下那些设置不完整权限对应的菜单
             */
            for (int i = 0; i < permissions.size(); i++) {
                Permission permission =  permissions.get(i);
                if (permission.getPermissionCode().endsWith("query") || permission.getPermissionCode().endsWith("view")) {
                    Permission criteria = new Permission();
                    criteria.setId(permission.getParentId());
                    criteria.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
                    Permission dbPermission = permissionMapper.selectOne(criteria);
                    // 当查询的数据存在并且原集合中不包含查询出的数据，就将数据添加到extraPermissions中去
                    if (dbPermission != null && !permissions.contains(dbPermission)) {
                        permissions.add(dbPermission);
                    }
                }
            }
        }

        // 排序
        Collections.sort(permissions);

        return permissions;
    }

    @Override
    public Set<Permission> getPermissionByUsername(String username) {

        User criteria = new User();
        criteria.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        criteria.setUsername(username);

        User dbUser = userMapper.selectOne(criteria);

        List<Permission> list = this.getPermissionByRole(dbUser.getRoleId(), false);

        if (CollectionUtils.isEmpty(list)) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        Set<Permission> set = new HashSet<>();
        for (Permission permission : list) {
            set.add(permission);
        }
        return set;
    }

}
